#include "crc.h"
#include "gpio.h"
#include "speed_cntr.h"
#include "tim.h"
#include "modbus.h"
#include "math.h"
#include "user_device.h"
#include "user_global.h"
#include "usart.h"
#include "wwdg.h"
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>

#define KEY_STOP_TIMER 0xFFFFFFFF
#define SHAKE_LASTTIME 2000                      // 按键触发后，去抖确认时长us
#define KEY_PUSHED_CONFIRM_LASTTIME 100000       // 按键触发后，确认持续时长us
#define KEY_PUSHED_LONG_CONFIRM_LASTTIME 8000000 // 按键触发后，长按确认持续时长us
#define KEY_EVENT_COUNT 3

#define MAX_RETRY_TIMES 1
#define MAX_MACHINE_OCUNT KEY_COUNT

#define SET_SPECIFIC_BIT(var, bit, value) ((var) = ((var) & ~(1U << (bit))) | ((value) << (bit)))


uint8_t server_address = 0x10;

// 传感器有效标志，只要检测到传感器发生沿变化，认为有效
bit ready_active[STATION_COUNT] = {0};
bit fixed_active = 1;
bit hat_active = 1;
bit tube_active = 1;

bit rack_ready_export = 0; // T1动作后，确认rack已在export到位时为1
bit pending_action = 0;    // 新动作
uchar pending_role = 0;    // 动作请求类别: 0 key1按键动作请求 1 key2按键动作请求; 2上位机动作
extern jmp_buf main_loop_env;
ulong import_stamp, export_stamp;
ulong key_stamp[3] = {KEY_STOP_TIMER};
ulong shake_stamp[3] = {KEY_STOP_TIMER};
ulong key_longtime_stamp[3] = {KEY_STOP_TIMER};
uchar event[KEY_EVENT_COUNT];                   // 左右缓冲输入事件
ushort auto_key_pending[KEY_EVENT_COUNT] = {0}; // 按键触发事件申请的动作计数

uchar me_state[MAX_MACHINE_OCUNT] = {ME_STATE_IDLE};
uchar me_retry[MAX_MACHINE_OCUNT] = {0};
uchar me_lastEvent[MAX_MACHINE_OCUNT] = {0}; // 最后一次记录的异常事件
bit high_priority_me = 0;
uchar me_max_retry_times[MAX_MACHINE_OCUNT] = {MAX_RETRY_TIMES, MAX_RETRY_TIMES, MAX_RETRY_TIMES};
uchar me_should_wait_ready[MAX_MACHINE_OCUNT] = {0};
uchar import_need_close_gate[2] = {0};
bit modbus_key_trigger[KEY_COUNT] = {0};
bit mkey_changed[KEY_COUNT] = {0};
ulong mkey_stamp[KEY_COUNT] = {TIMER_STOPED, TIMER_STOPED, TIMER_STOPED};

//
uint32_t TrackExitMotor_coordinate[TRACK_EXIT_MOTOR_SITE_COUNT] = {0};
const uint32_t motorSafetyReturnOrder[] = {R2, V3, S1, S2, V1, V2};
bit led_update_disable = 0;
int sampleRackOnConveyor = 0;

int hasSampleRack_onCnvBelt(void);
int conveyorBelt_motor_start(void);
bit Do_Action_R2_Move_LimitDown(uchar isTallTube);

enum LED_MODE
{
    LED_ON_CONST,        // 常亮
    LED_OFF_CONST,       // 常灭
    LED_BLINK_INFO,      // 闪烁
    LED_BLINK_WARNINNG,  // 闪烁
    LED_BLINK_ERR,       // 闪烁
    LED_BLINK_FATAL,     // 闪烁
    LED_BLINK_AUTOMATIC, // 闪烁

    LED_MODE_COUNT,
};

LED_CNTRL led_mode_pool[LED_MODE_COUNT] = {
    {0xFFFF, 1, 0},
    {0xFFFF, 0, 1},
    {0xFFFF, 1000, 1000},
    {0xFFFF, 500, 500},
    {0xFFFF, 200, 200},
    {0xFFFF, 100, 100},
    {0xFFFF, 2000, 2000},
};

#define MAX_FIX_COUNT 20
FIX_VALUE fix;

int all_zeros(char arr[], int size)
{
    int i = 0;
    for (; i < size; i++)
    {
        if (arr[i] != 0)
        {
            return 0;
        }
    }
    return 1;
}

//////////////////////////////////////////////////////////////
void Update_IO(void)
{
    uint8_t rack_flag = 0;
    int i = 0;

    ro_bit.s1_at_home = IO_Read(IO_S1_HOME);
    ro_bit.s2_at_home = IO_Read(IO_S2_HOME);
    ro_bit.v1_at_home = IO_Read(IO_V1_HOME);
    ro_bit.v2_at_home = IO_Read(IO_V2_HOME);
    ro_bit.v3_at_home = IO_Read(IO_V3_HOME);
    ro_bit.s1_at_limit = IO_Read(IO_S1_LIMIT);
    ro_bit.s2_at_limit = IO_Read(IO_S2_LIMIT);
    ro_bit.r2_at_home = IO_Read(IO_R2_HOME);

    ro_bit.basket_exist_prel = IO_Read(IO_BASKETL_EXIST);
    ro_bit.basket_exist_prer = IO_Read(IO_BASKETR_EXIST);

    if (ro_bit.tube_exist != IO_Read(IO_TUBE_EXIST))
    {
        ro_bit.tube_exist = IO_Read(IO_TUBE_EXIST);
        tube_active = 1;
    }
    if (ro_bit.rack_fixed != IO_Read(IO_RACK_FIXED))
    {
        ro_bit.rack_fixed = IO_Read(IO_RACK_FIXED);
        fixed_active = 1;
    }
    if (ro_bit.hat_exist != IO_Read(IO_HAT_EXIST))
    {
        ro_bit.hat_exist = IO_Read(IO_HAT_EXIST);
        hat_active = 1;
    }

    if (ro_bit.rack_ready_importl != IO_Read(IO_IMPORTL_READY))
    {
        ro_bit.rack_ready_importl = IO_Read(IO_IMPORTL_READY);
        if (!ro_bit.rack_ready_importl)
            ro_word.rack_importl_refer_count = 0;
        ready_active[IMPORTL] = 1;
    }

    if (ro_bit.rack_ready_importr != IO_Read(IO_IMPORTR_READY))
    {
        ro_bit.rack_ready_importr = IO_Read(IO_IMPORTR_READY);
        if (!ro_bit.rack_ready_importr)
            ro_word.rack_importr_refer_count = 0;
        ready_active[IMPORTR] = 1;
    }

    if (ro_bit.rack_ready_export != IO_Read(IO_EXPORT_READY))
    {
        ro_bit.rack_ready_export = IO_Read(IO_EXPORT_READY);
        if (!ro_bit.rack_ready_export)
        {
            ro_word.rack_export_refer_count = 0;
            rack_ready_export = 0;
        }
        ready_active[EXPORT] = 1;
    }

    if (ro_bit.rack_exist_prel != IO_Read(IO_PREL_EXIST))
    {
        ro_bit.rack_exist_prel = IO_Read(IO_PREL_EXIST);
        if (!IO_Read(IO_S1_HOME) && ro_bit.rack_exist_prel)
            Start_Beep(BEEP_ERR);
    }

    if (ro_bit.rack_exist_prer != IO_Read(IO_PRER_EXIST))
    {
        ro_bit.rack_exist_prer = IO_Read(IO_PRER_EXIST);
        if (!IO_Read(IO_S2_HOME) && ro_bit.rack_exist_prer)
            Start_Beep(BEEP_ERR);
    }
}

///////////////////////////////////////////////////////////////
/// app_args
uint32_t test_delay_nonBlock(uint32_t *stamp, uint32_t time_ms)
{
    uint32_t time_span = time_ms;
    if (*stamp == TIMER_STOPED)
        TIMER_START(*stamp);
    if (TIMER_MS(*stamp, time_span))
    {
        TIMER_STOP(*stamp);
        return 1;
    }
    return 0;
}

bit Ignore_Importl_Ready()
{
    return rw_word.app_arg1.ignore_importl_ready;
}

bit Ignore_Importr_Ready()
{
    return rw_word.app_arg1.ignore_importr_ready;
}

bit Ignore_Export_Ready()
{
    return rw_word.app_arg1.ignore_export_ready;
}

bit Ignore_Import_Ready(uchar index)
{
    assert(index < 2);
    if (index == 0)
        return rw_word.app_arg1.ignore_importl_ready;
    if (index == 1)
        return rw_word.app_arg1.ignore_importr_ready;
    return 0;
}

///////////////////////////////////////////////////////////////
// 返回该节点是否存在试管架
bit Rack_Exist(uchar station)
{
    // 如果忽略传感器错误，且未检测到传感器有效，使用refer_count
    // 如果未忽略传感器错误，或检测到传感器有效，使用传感器状态或refer_count
    switch (station)
    {
    case IMPORTL:
        if (Ignore_Import_Ready(IMPORTL) && !ready_active[IMPORTL])
            return ro_word.rack_importl_refer_count > 0;
        else if (ro_bit.rack_ready_importl || ro_word.rack_importl_refer_count)
            return 1;

        break;
    case IMPORTR:
        if (Ignore_Import_Ready(IMPORTR) && !ready_active[IMPORTR])
            return ro_word.rack_importr_refer_count > 0;
        else if (ro_bit.rack_ready_importr || ro_word.rack_importr_refer_count)
            return 1;

        break;
    case EXPORT:
        if (Ignore_Export_Ready() && !ready_active[EXPORT])
            return ro_word.rack_export_refer_count > 0;
        else if (ro_bit.rack_ready_export || ro_word.rack_export_refer_count)
            return 1;
        break;
    default:
        break;
    }
    return 0;
}

///////////////////////////////////////////////////////////////
// start event

bit Modbus_Key_Trigger(uchar index)
{
    bit v;
    if (modbus_key_trigger[index])
    {
        modbus_key_trigger[index] = 0;
        if (mkey_stamp[index] == TIMER_STOPED ||
            (mkey_stamp[index] != TIMER_STOPED && TIMER_OUT(mkey_stamp[index], 50000)))
        {
            TIMER_START(mkey_stamp[index]);

            v = index ? rw_bit.start_r : rw_bit.start_l;
            if (v == 0)
            {
                if (me_state[index] == ME_STATE_WAIT || me_state[index] == ME_STATE_WORKING || me_state[index] == ME_STATE_RESET)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                if (me_state[index] == ME_STATE_IDLE)
                    return 1;
            }
        }
    }
    return 0;
}

// 检测到按键按下返回1,否则返回0
bit Key_Pushed(uchar key)
{
    bit pressed;
    bit key_long_pressed;
    uchar key_index = key - IO_STARTL_PRESSED;
    assert(key == IO_STARTL_PRESSED || key == IO_STARTR_PRESSED || key == IO_STOP_PRESSED)

        pressed = IO_Read(key);
    // 检测按键状态变化
    if (pressed != Test_Bit(RO_BIT_FIRST, STARTL_PRESSED + key_index))
    {
        Set_Bit(RO_BIT_FIRST, STARTL_PRESSED + key_index, pressed);
        if (pressed)
        {
            if (key_stamp[key_index] == TIMER_STOPED)
            {
                TIMER_START(key_stamp[key_index]);
            }
            TIMER_START(shake_stamp[key_index]);
        }
        else
        {
        }
    }

    if (!pressed)
    {
        if (shake_stamp[key_index] != TIMER_STOPED && SystemTick() - shake_stamp[key_index] > SHAKE_LASTTIME)
        {
            TIMER_STOP(key_stamp[key_index]);
            TIMER_STOP(shake_stamp[key_index]);
            TIMER_STOP(key_longtime_stamp[key_index]);
        }
        return 0;
    }
    else
    {

        if (key_stamp[key_index] != TIMER_STOPED)
            (&ro_word.startl_pressed_duration)[key_index] = (SystemTick() - key_stamp[key_index]) / 1000;
    }

    if (key_longtime_stamp[key_index] != TIMER_STOPED && SystemTick() - key_longtime_stamp[key_index] > KEY_PUSHED_LONG_CONFIRM_LASTTIME)
    {
        TIMER_STOP(key_longtime_stamp[key_index]);
        if (!key_index)
            rw_bit.key_long_pressed_l = 1;
        else
            rw_bit.key_long_pressed_r = 1;

        key_long_pressed = ro_bit.stop_pressed;
        ro_bit.stop_pressed = key_long_pressed ? 0 : 1;
        if (ro_bit.stop_pressed)
        {
            Start_Beep(BEEP_WARNING);
            Set_Starts_Led(0, LED_BLINK_AUTOMATIC);
            Set_Starts_Led(1, LED_BLINK_AUTOMATIC);
            led_update_disable = 1;
        }
        else
        {
            Start_Beep(BEEP_INFO2);
            led_update_disable = 0;
            Set_Starts_Led(0, LED_OFF_CONST);
            Set_Starts_Led(1, LED_OFF_CONST);
        }
    }

    if (key_stamp[key_index] != TIMER_STOPED && SystemTick() - key_stamp[key_index] > KEY_PUSHED_CONFIRM_LASTTIME)
    {
        TIMER_START(key_longtime_stamp[key_index]);
        TIMER_STOP(key_stamp[key_index]);
        return 1;
    }

    return 0;
}

// 软开关指示灯控制函数,周期 == 亮-->灭 | 亮-->灭 |......
void Key_Led_Ctrl(uchar n)
{
#define LED_BLINK_FORERVER 0xFFFF // led 始终按设定模式执行

#define STATE_READY_TO_LIGHT_OFF 0 // 准备置灭LED
#define STATE_READY_TO_LIGHT_ON 1  // 准备点亮LED

    static uchar led_state[2] = {0};
    static ulong led_on_time[2] = {0};
    static ulong led_off_time[2] = {0};
    static ushort led_on_duration[2] = {0};

    LED_CNTRL *led = &rw_word.led_cnt[n];
    if (led_on_duration[n] != led->led_on_duration)
    {
        if (!led_on_duration[n])
        {
            IO_Set(IO_STARTL_LED + n);
            led_state[n] = STATE_READY_TO_LIGHT_OFF;
            led_on_time[n] = SystemTick();
        }
        led_on_duration[n] = led->led_on_duration;
    }

    if (led->led_blink_times)
    {
        switch (led_state[n])
        {
        case STATE_READY_TO_LIGHT_OFF:
            if (led->led_off_duration)
            {
                // 亮时间超时，准备置灭
                if ((SystemTick() - led_on_time[n]) > (ulong)led->led_on_duration * 1000)
                {
                    IO_Reset(IO_STARTL_LED + n);
                    led_state[n] = STATE_READY_TO_LIGHT_ON;
                    led_off_time[n] = SystemTick();
                }
            }
            else
            {
                led_state[n] = STATE_READY_TO_LIGHT_ON;
            }
            break;
        case STATE_READY_TO_LIGHT_ON:
            if (led->led_on_duration)
            {
                // 灭时间超时，准备点亮
                if ((SystemTick() - led_off_time[n]) > (ulong)led->led_off_duration * 1000)
                {
                    IO_Set(IO_STARTL_LED + n);
                    led_state[n] = STATE_READY_TO_LIGHT_OFF;
                    led_on_time[n] = SystemTick();
                    if (led->led_blink_times != LED_BLINK_FORERVER)
                        --led->led_blink_times;
                }
            }
            else
            {
                led_state[n] = STATE_READY_TO_LIGHT_OFF;
            }
        default:
            break;
        }
    }
}

void Set_Starts_Led(uchar n, uchar model)
{
    if (led_update_disable)
        return;
    memcpy(&rw_word.led_cnt[n], &led_mode_pool[model], sizeof(LED_CNTRL));
}

bit All_Starters_Idle()
{
    uchar i;
    for (i = 0; i < KEY_START_COUNT; ++i)
    {
        if (me_state[i] != ME_STATE_IDLE)
            return 0;
    }
    return 1;
}

bit Other_Starters_Idle(uchar starter)
{
    uchar i;
    for (i = 0; i < KEY_START_COUNT; ++i)
    {
        if (i == starter)
            continue;

        if (me_state[i] != ME_STATE_IDLE)
            return 0;
    }
    return 1;
}

bit All_Starters_Wait()
{
    uchar i;
    for (i = 0; i < KEY_START_COUNT; ++i)
    {
        if (me_state[i] != ME_STATE_WAIT)
            return 0;
    }
    return 1;
}

void Clear_Event(uchar index)
{
    event[index] = EVENT_NONE;
}

void Post_Event(uchar index, uchar etype)
{
    if (index < KEY_EVENT_COUNT)
        event[index] = etype;
}

uchar Take_Event(uchar index)
{
    uchar e;
    if (index >= KEY_EVENT_COUNT)
        return 0;
    e = event[index];
    event[index] = 0;
    return e;
}

void Me_Init(uchar index)
{
    auto_key_pending[index] = 0;
    Clear_Event(index);
    me_lastEvent[index] = EVENT_NONE;
}



// 按钮开关按键触发处理
void Process_Start_Event(uchar index)
{
    bit key_pushed = Key_Pushed(!index ? IO_STARTL_PRESSED : IO_STARTR_PRESSED);

    if (key_pushed == 0)
        key_pushed = Modbus_Key_Trigger(index);

    if (!key_pushed)
        return;

    mkey_changed[index] = 1;
    Start_Beep(BEEP_USER_KEY_PUSHED);

    switch (me_state[index])
    {
    case ME_STATE_IDLE:
        me_state[index] = ME_STATE_WAIT;
        Set_Starts_Led(index, LED_BLINK_INFO);
        Me_Init(index);
        me_retry[index] = 0;
        me_max_retry_times[index] = MAX_RETRY_TIMES;
        me_should_wait_ready[index] = 0;
        break;
    case ME_STATE_WAIT:
        if (!IO_Read(IO_S1_HOME + index))
        {
            me_state[index] = ME_STATE_RESET;
            Do_Action_Reset_NoWait(index);
            break;
        }
        me_state[index] = ME_STATE_IDLE;
        Set_Starts_Led(index, LED_OFF_CONST);
        break;
    case ME_STATE_WORKING:
        if (!IO_Read(IO_S1_HOME + index))
        {
            me_state[index] = ME_STATE_RESET;
            Do_Action_Reset_NoWait(index);
            break;
        }
        else
        {
            Do_Action_Stop(index);
            me_state[index] = ME_STATE_IDLE;
            Set_Starts_Led(index, LED_OFF_CONST);
        }
        break;
    case ME_STATE_RESET:
        Do_Action_Stop(index);
        me_state[index] = ME_STATE_IDLE;
        Set_Starts_Led(index, LED_OFF_CONST);
        break;
    }
}

void Check_Improper_Input(void)
{
    uchar index = 0;
    for (index = 0; index < 2; ++index)
    {
        if (!IO_Read(IO_S1_HOME + index) && IO_Read(IO_PREL_EXIST + index))
            Start_Beep(BEEP_ERR);
    }
}

bit Can_Lock_Export(bit ignore_error)
{
    if (ps_server_busy)
        return 0;
    if (ro_word.server_status != STATUS_IDLE && !ignore_error)
        return 0;

    if (Rack_Exist(EXPORT) && rack_ready_export)
        return 0;

    return 1;
}

bit S_Can_Start(uchar index)
{
    if (!IO_Read(IO_BASKETL_EXIST + index))
        return 0;

    if (Test_Bit(RW_BIT_FIRST, 7 + index))
        return 0;

    return 1;
}

bit S_Need_Wait_Ready(uchar index)
{
    if (!IO_Read(IO_BASKETL_EXIST + index))
        return 1;
    return 0;
}

bit Maybe_Terminated(uchar index)
{
    switch (index)
    {
    case S1:
    case S2:
        // 如果检测到试管架存在，停止动作
        if (IO_Read(IO_PREL_EXIST + index - S1))
        {
            Do_Action_Stop(index);
            return 1;
        }
        break;
    default:
        return 0;
    }
    return 0;
}



void Process_Rack(uchar index)
{
    uchar event = 0;
    bit ignore_error = 0;

    static ulong me_stamp[KEY_START_COUNT] = {0};
    assert(index < KEY_START_COUNT);

    switch (me_state[index])
    {
    case ME_STATE_IDLE:
        break;
    case ME_STATE_WAIT:
        if (!Other_Starters_Idle(index))
        {
            if (All_Starters_Wait() && high_priority_me == index)
            {
                // 所有starter都在等待，且当前等待优先级最高
            }
            else if (All_Starters_Wait() && high_priority_me != index)
            {
                // 分析是或否高优先级的受到了硬件条件制约
                if (!S_Can_Start(high_priority_me))
                    high_priority_me = index;
            }
            else
                return;
        }
        if (!Can_Lock_Export(1))
            return;

        if (S_Need_Wait_Ready(index))
            me_should_wait_ready[index] = 1;

        if (!S_Can_Start(index))
            return;
        Me_Init(index);
        TIMER_STOP(me_stamp[index]);
        me_state[index] = ME_STATE_WORKING;
        Set_Starts_Led(index, LED_ON_CONST);
        ro_word.server_status = STATUS_IDLE;
        break;
    case ME_STATE_WORKING:
        if (ps_server_busy)
            return;
        event = Take_Event(index);
        if (event == EVENT_BUF_EMPTY || event == EVENT_LIMIT_ERROR || event == EVENT_EXPORT_READY_ERROR || ro_word.server_status != STATUS_IDLE)
        {
            me_lastEvent[index] = event;
            if (++me_retry[index] >= me_max_retry_times[index])
            {
                high_priority_me = index ? KEY_STARTL : KEY_STARTR;
                me_state[index] = ME_STATE_IDLE;
                // Do_Action_Reset_NoWait(index);
                if (event == EVENT_BUF_EMPTY)
                    Set_Starts_Led(index, LED_OFF_CONST);
                else
                {
                    Set_Starts_Led(index, LED_BLINK_ERR);
                    Start_Beep(BEEP_ERR);
                }
                break;
            }
            else
            {
                // 如果空事件,未到达最大次数重新等待
                if (event == EVENT_BUF_EMPTY)
                {
                    me_state[index] = ME_STATE_WAIT;
                    me_should_wait_ready[index] = 0;
                    Set_Starts_Led(index, LED_BLINK_INFO);
                    high_priority_me = index ? KEY_STARTL : KEY_STARTR;
                }
                if (ro_word.server_status != STATUS_IDLE)
                    ro_word.server_status = STATUS_IDLE;
            }
        }
        else
        {

        }


        // 重试动作次数小于最大重试次数，忽略错误
        ignore_error = (me_retry[index] < MAX_RETRY_TIMES);
        if (Can_Lock_Export(ignore_error) && index < KEY_STOP && S_Can_Start(index))
        {
            // 首次推送，如果不需要等待不等待
            bit me_not_need_wait = !auto_key_pending[index] && !me_should_wait_ready[index];

            if (me_stamp[index] == TIMER_STOPED)
                TIMER_START(me_stamp[index]);
            if ((me_stamp[index] != TIMER_STOPED && TIMER_OUT(me_stamp[index], 1000000)) || me_not_need_wait)
            {
                me_should_wait_ready[index] = 0;
                TIMER_STOP(me_stamp[index]);
                ++auto_key_pending[index];
                if (!auto_key_pending[index])
                    ++auto_key_pending[index];
                rw_word.action = TRANS_IN;
                pending_action = 1;
                rw_word.action_arg[0] &= ~0x01;
                rw_word.action_arg[0] |= (index & 0x01);
                pending_role = !index ? ACTION_PENDING_KEY1_EVENT : ACTION_PENDING_KEY2_EVENT;
            }
        }
        break;
    case ME_STATE_RESET:
        if (Maybe_Terminated(index))
        {
            Set_Starts_Led(index, LED_BLINK_WARNINNG);
            me_state[index] = ME_STATE_IDLE;
            transportIn.endflag = 1;
            break;
        }

        // 等待电机复位完成
        if (srd_desc[index].srd->running)
            return;

        import_need_close_gate[index] = 1;

        Set_Starts_Led(index, LED_OFF_CONST);

        if (!srd_desc[S1 + index].srd->hit_home)
        {
            Set_RO_Bit(S1_HOME_SENSOR_ERROR + index);
            ro_word.server_status = S1_STATUS_HOME_SENSOR_ERROR + index;
            Set_Starts_Led(index, LED_BLINK_ERR);
        }
        else
        {
            Reset_RO_Bit(S1_HOME_SENSOR_ERROR + index);
        }
        me_state[index] = ME_STATE_IDLE;
        transportIn.endflag = 1;
        break;
    }

    if (!ps_server_busy && !pending_action)
    {
        if (import_need_close_gate[index])
        {
            pending_action = 1;
            rw_word.action = CLOSE_BUFL_GATE + (index << 1);
            import_need_close_gate[index] = 0;
        }
    }
}

bit Fix_Level()
{
    static uchar fix_filter = 0xff;
    static uchar fix_sum = 8;
    bit state = IO_Read(IO_RACK_FIXED);
    fix_sum -= ((fix_filter & 0x80) >> 7);
    fix_filter = (fix_filter << 1) | state;
    fix_sum += state;
    return (fix_sum > 4);
}

void Reset_Fix()
{
    fix.index = 0;
    fix.exist = 0;
    fix.hat_exist = 0;
    fix.state = Fix_Level();
    fix.enable = 1;
}

void Update_fix()
{
    bit fix_level;

    if (!fix.enable)
        return;

    fix_level = Fix_Level();
    if (fix.state != fix_level)
    {
        fix.state = fix_level;
        if (fix.state)
        {
            if (IO_Read(IO_HAT_EXIST))
                fix.hat_exist |= (1 << fix.index);
            else
                fix.hat_exist &= ~(1 << fix.index);
            fix.hat_exist &= 0x1F;

            if (IO_Read(IO_TUBE_EXIST))
                fix.exist |= (1 << fix.index);
            else
                fix.exist &= ~(1 << fix.index);
            fix.exist &= 0x1F;
            fix.exist |= fix.hat_exist ? (1 << 5) : 0;
            ++fix.index;
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// machine base

void Step(uchar role, bit level)
{
    // IO_Z_STEP(level);
}

void Start_Timer(uchar role)
{
    timer_enable(srd_desc[role].timer);
}

void Set_Timer(uchar role)
{
    ushort micro = srd_desc[role].srd->micro;
    ushort tick = FREQ_TABLE(srd_desc[role].srd->speed_index);
    if (micro)
    {
        // 默认使用16细分，如果使用了其他细分,改变pwm的频率
        tick = tick * FACILITYMICRO / (micro > FACILITYMICRO ? FACILITYMICRO : micro);
        tick = tick > MAX_C ? MAX_C : tick;
    }
    timer_autoreload_value_config(srd_desc[role].timer, tick * 2);
    timer_channel_output_pulse_value_config(srd_desc[role].timer, srd_desc[role].timer_ch, tick);
}

void Stop_Timer(uchar role)
{
    timer_disable(srd_desc[role].timer);
}

// 启动电机
void Start_Motor(uint8_t role)
{
    // SpeedRampData *srd = srd_desc[role].srd;
    long *distance;
    if (role == R1 || role == R2)
        distance = (long *)&ro_word.rn_mi[role].distance;
    else
        distance = (long *)&ro_word.mi[role].distance;
    *distance = 0;
    Set_Timer(role);
    Start_Timer(role);

    IO_WRITE(IO_S1_CW + role, srd[role].dir);
    IO_WRITE(IO_S1_EN + role, 1);
    IO_WRITE(IO_S1_LOCK + role, 0);
}

// 停止电机
void Stop_Motor(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;
    long *distance;
    ushort *duration;

    if (role == R1 || role == R2)
    {
        distance = (long *)&ro_word.rn_mi[role].distance;
        duration = (ushort *)&ro_word.rn_mi[role].duration;
    }
    else
    {
        distance = (long *)&ro_word.mi[role].distance;
        duration = (ushort *)&ro_word.mi[role].duration;
    }

    if (srd->dir == CCW)
        *distance = -srd->step_count;
    else
        *distance = srd->step_count;
    *duration = (ushort)((SystemTick() - srd->start_time) / US_TO_TICK(1000));
    srd->need_cleanup = 0;
    srd->running = 0;
    if (role == V3)
    {
        transportIn.site = transportIn.site_previous;
        if (!IO_Read(IO_V3_HOME))
            return;
    }
    IO_WRITE(IO_S1_EN + role, 0);
    IO_WRITE(IO_S1_LOCK + role, 1);
}

void Init_Move(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;
    uchar home = srd_desc[role].home;
    uchar limit = srd_desc[role].limit;
    uchar limit2 = srd_desc[role].limit2;
    uchar limit3 = srd_desc[role].limit3;

    srd->init = Start_Motor;
    srd->step = Step;
    srd->start_timer = Set_Timer;
    srd->stop_timer = Stop_Timer;
    srd->cleanup = Stop_Motor;
    srd->home_state = IO_Read(home);
    srd->limit_state = IO_Read(limit);
    srd->limit_state2 = IO_Read(limit2);
    srd->limit_state3 = IO_Read(limit3);
    srd->hit_home = 0;
    srd->hit_limit = 0;
    srd->hit_limit2 = 0;
    srd->hit_limit3 = 0;
}
int r2_limit_count = 0;
// 执行移动指令时, 每一步调用一次
void Move_To_Update(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;
    uchar home = srd_desc[role].home;
    uchar limit = srd_desc[role].limit;
    uchar limit2 = srd_desc[role].limit2;
    uchar limit3 = srd_desc[role].limit3;

    Update_IO();

    if (IO_Read(home) && (IO_Read(home) != srd->home_state))
    {
        srd->home_state = !srd->home_state;
        srd->hit_home = 1;
        if (role == R1 || role == R2)
            ro_word.rn_pos[role-R1] = 0;
        else
            ro_word.pos[role] = 0;
        srd->stamp = SystemTick();
        srd->step_left = labs(srd->target);
    }
    else if (limit && (IO_Read(limit) != srd->limit_state))
    {
        srd->limit_state = !srd->limit_state;
        srd->hit_limit = 1;
        if (srd->limit_state && srd->step_left > srd->limit_step)
        {
            srd->step_left = srd->limit_step;
        }
    }
    else if (limit2 && (IO_Read(limit2) != srd->limit_state2))
    {
        srd->limit_state2 = !srd->limit_state2;
        srd->hit_limit2 = 1;
        if (srd->limit_state2 && srd->step_left > srd->limit2_step)
            srd->step_left = srd->limit2_step;
    }
    else if (limit3 && (IO_Read(limit3) != srd->limit_state3))
    {
        srd->limit_state3 = !srd->limit_state3;
        srd->hit_limit3 = 1;
        if (srd->limit_state3 && srd->step_left > srd->limit3_step)
            srd->step_left = srd->limit3_step;
    }
    else
    {
        if (role == R1 || role == R2)
            ro_word.rn_pos[role-R1] += srd->step_offset;
        else
            ro_word.pos[role] += srd->step_offset;
    }
}

void T1_Move_To_Update(uchar role)
{
    Move_To_Update(role);
    Update_fix();
}

// 执行移动指令时, 每一步调用一次
void Reset_To_Update(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;
    uchar home = srd_desc[role].home;
    uchar limit = srd_desc[role].limit;

    Update_IO();

    if (IO_Read(home) != srd->home_state)
    {
        srd->home_state = !srd->home_state;
        srd->hit_home = 1;
        if (role == R1 || role == R2)
            ro_word.rn_pos[role - R1] =0;
        else
            ro_word.pos[role] = 0;
        srd->stamp = SystemTick();
        srd->step_left = labs(srd->target);
    }
    if (IO_Read(limit) != srd->limit_state)
    {
        srd->limit_state = !srd->limit_state;
        srd->hit_limit = 1;
    }
    else
    {
        if (role == R1 || role == R2)
            ro_word.rn_pos[role-R1] += srd->step_offset;
        else
            ro_word.pos[role] += srd->step_offset;
    }
}

void Do_Action_Stop(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;

    if (srd->running)
    {
        Stop_Timer(role);
        Stop_Motor(role);
    }
}

bit Do_Action_Reset(uchar role, ushort reset_speed)
{
    SpeedRampData *srd = srd_desc[role].srd;

    if (Maybe_Terminated(role))
        return 0;

    Init_Move(role);
    srd->update = Reset_To_Update;
    srd->target = srd->home_state ? srd->reset_step : -srd->reset_step;
    speed_cntr_Move(srd,
                    srd->home_state ? rw_word.mp[role].max_distance : -rw_word.mp[role].max_distance,
                    reset_speed);

    while (srd->running)
    {
        if (Maybe_Terminated(role))
            return 0;
        Process_Main_Loop();
    }

    if (srd_desc[role].home && !srd->hit_home)
    {
        Set_RO_Bit(S1_HOME_SENSOR_ERROR + role);
        ro_word.server_status = S1_STATUS_HOME_SENSOR_ERROR + role;
        return 0;
    }
    else
        Reset_RO_Bit(S1_HOME_SENSOR_ERROR + role);

    if (V3 == role)
    {
       transportIn.site = TRACK_EXIT_MOTOR_SITE_ORIGIN;
       transportIn.site_previous = TRACK_EXIT_MOTOR_SITE_ORIGIN;
    }
    // 复位完成，移动到负坐标位置
    Do_Action_Move_To(role, -srd->reset_step, rw_word.mp[role].max_speed);
    return 1;
}

void Do_Action_Reset_NoWait(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;

    ushort speed = rw_word.mp[role].max_speed;
    if(role == S1 || role == S2)
        speed = ((ushort*)&rw_word.s1_max_speed2)[role];

    Init_Move(role);
    srd->update = Reset_To_Update;
    srd->target = srd->home_state ? srd->reset_step : -srd->reset_step;
    speed_cntr_Move(srd,
                    srd->home_state ? rw_word.mp[role].max_distance : -rw_word.mp[role].max_distance,
                    speed);
    if (V3 == role)
    {
       transportIn.site = TRACK_EXIT_MOTOR_SITE_ORIGIN;
       transportIn.site_previous = TRACK_EXIT_MOTOR_SITE_ORIGIN;
    }
}

void Do_Action_Move_To(uchar role, long target, ushort speed)
{
    SpeedRampData *srd = srd_desc[role].srd;

    Init_Move(role);
    srd->update = Move_To_Update;
    srd->target = target;
    if (role == R1 || role == R2)
    speed_cntr_Move(srd,
                    target - ro_word.rn_pos[role-R1],
                    speed);
    else
    speed_cntr_Move(srd,
                    target - ro_word.pos[role],
                    speed);
    while (srd->running)
        Process_Main_Loop();
}

int Do_Action_DegradedMotor_Move_To(void)
{
    uchar role = V3;
    long target = -TrackExitMotor_coordinate[6-transportIn.site_previous];
    SpeedRampData *srd = srd_desc[role].srd;

    Init_Move(role);
    srd->update = Move_To_Update;
    srd->target = target;

    speed_cntr_Move(srd,
                    target - ro_word.pos[role],
                    rw_word.mp[role].max_speed);

    while (srd->running)
        Process_Main_Loop();
    return 1;
}

// machine base end
///////////////////////////////////////////////////////////////

void Clear_Limit(uchar role)
{
    srd_desc[role].limit2 = NULL_IN;
    srd_desc[role].limit3 = NULL_IN;
}

void Init_S_Move(uchar role)
{
    Init_Move(role);
}

// 停机，停止所有在运行的电机
void Do_Action_S_Stop(uchar role)
{
    Do_Action_Stop(role);
}

void Do_Action_S_Move_To(uchar role, long target, ushort speed)
{
    Do_Action_Move_To(role, target, speed);
}

/*!
 * V1/V2/V3/V4 打开闸门
 * role : V1;V2;V3;V4
 * \brief Do_Action_V_Open_Gate
 * V1 V2 带有传动结构，打开阀门时实际是自身执行了关闭动作
 */
uchar Do_Action_V_Open_Gate(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;
    uchar home = srd_desc[role].home;

    if (role == V3)
        return Do_Action_Reset(V3,rw_word.mp[V3].max_speed);

    if(IO_Read(home))
    {
        // 在复位位置，且坐标不正确，清除坐标，
        // 因为检测到复位光耦遮挡，且坐标为关闭闸门坐标值，发送打开/关闭阀门将会不动作
        if(ro_word.pos[role] > srd->reset_step*2)
            ro_word.pos[role] = 0;
        return 1;
    }

    return Do_Action_Reset(role,rw_word.mp[role].max_speed);
}

/*!
 * V1/V2/V3/V4 关闭闸门
 * role : V1;V2;V3;V4
 * \brief Do_Action_V_Open_Gate
 * V1 V2 带有传动结构，关闭阀门时实际是自身执行了打开动作
 */
bit Do_Action_V_Close_Gate(uchar role)
{
    SpeedRampData *srd = srd_desc[role].srd;
    uchar home = srd_desc[role].home;

    assert(role >= V1 && role <= V3);

    if (role == V3)
    {
        transportIn.site_previous = TRACK_EXIT_MOTOR_SITE_START;
        return Do_Action_DegradedMotor_Move_To();
    }

    Init_Move(role);
    srd->update = Move_To_Update;
    srd->target = ((short*)&rw_word.v1_close_pos)[role - V1];

    speed_cntr_Move(srd,
                    srd->target - ro_word.pos[role],
                    rw_word.mp[role].max_speed);

    while(srd->running)
        Process_Main_Loop();

    // 关闭闸门动作后还在复位(打开闸门)位置
    if(IO_Read(home))
    {
        ro_word.server_status = V1_STATUS_MOTOR_ERROR + role - V1;
        Set_RO_Bit(V1_MOTOR_ERROR + role - V1);
        return 0;
    }
    else
        Reset_RO_Bit(V1_MOTOR_ERROR + role - V1);
    return 1;
}

//////////////////////////////////////////////////////////////////////////////////

void Do_Action_StandBy()
{
    uchar i = 0;
    for (i = 0; i < MACHINE_COUNT; ++i)
        Do_Action_Stop(i);
}

void Do_Action_Home()
{
    uchar i = 0;
    uchar s_reset_flag[2] = {0};

    if(!IO_Read(IO_PREL_EXIST))
    {
        Do_Action_Reset_NoWait(S1);
        s_reset_flag[0] = 1;
    }
    if(!IO_Read(IO_PRER_EXIST))
    {
        Do_Action_Reset_NoWait(S2);
        s_reset_flag[1] = 1;
    }
    Do_Action_Reset_NoWait(V1);
    Do_Action_Reset_NoWait(V2);
    Do_Action_Reset_NoWait(V3);
    while(srd_desc[V1].srd->running || srd_desc[V2].srd->running || \
          srd_desc[V3].srd->running )
    {
        Maybe_Terminated(S1);
        Maybe_Terminated(S2);
        Process_Main_Loop();
    }
    for(i = 0; i < 3; ++i)
    {
        if(!srd_desc[V1 + i].srd->hit_home)
        {
            Write_RO_bit(V1_HOME_SENSOR_ERROR + i, 1, 1);
            ro_word.server_status = V1_STATUS_HOME_SENSOR_ERROR + i;
        }
        else
            Write_RO_bit(V1_HOME_SENSOR_ERROR + i, 0, 1);
    }

    // 复位完成后关闭闸门
    Do_Action_V_Close_Gate(V1);
    Do_Action_V_Close_Gate(V2);
    Do_Action_V_Close_Gate(V3);
    // 等待推入推出电机复位完成
    while(srd_desc[S1].srd->running || srd_desc[S2].srd->running)
    {
        Maybe_Terminated(S1);
        Maybe_Terminated(S2);
        Process_Main_Loop();
    }

    Do_Action_Reset_NoWait(V1);
    Do_Action_Reset_NoWait(V2);
    Do_Action_Reset_NoWait(V3);
    while(srd_desc[V1].srd->running || srd_desc[V2].srd->running || \
          srd_desc[V3].srd->running )
    {
        Process_Main_Loop();
    }
    for(i = 0; i < 3; ++i)
    {
        ushort valid_distance = ((short*)&rw_word.v1_close_pos)[i];
        valid_distance = (ushort)((float)valid_distance*0.75f);
        if(abs(ro_word.mi[V1+i].distance) < valid_distance)
            Do_Action_V_Open_Gate(V1 + i);
        else
            Do_Action_V_Close_Gate(V1 + i);
    }

    for(i = 0; i < 2; ++i)
    {
        if(!s_reset_flag[i])
            continue;

        if(!srd_desc[S1 + i].srd->hit_home)
        {
            Set_RO_Bit(S1_HOME_SENSOR_ERROR + i);
            ro_word.server_status = S1_STATUS_HOME_SENSOR_ERROR + i;
        }
        else
        {
            Reset_RO_Bit(S1_HOME_SENSOR_ERROR + i);
            // 复位完成，移动到负坐标位置
            Do_Action_Move_To(S1 + i, -srd_desc[S1 + i].srd->reset_step, rw_word.mp[S1 + i].max_speed);
        }
    }
    Do_Action_R2_Move_LimitDown(1);
    if(!IO_Read(IO_R2_HOME))
        Do_Action_Reset(R2,rw_word.mp[R2].max_speed);
    Do_Action_Reset_NoWait(V3);
    Start_Beep(ro_word.server_status == STATUS_IDLE ? BEEP_INFO : BEEP_ERR);
}

void Do_Action_Selftest(void)
{
    Update_IO();
    if( Rack_Exist(IMPORTL) || Rack_Exist(EXPORT) || Rack_Exist(IMPORTR))
    {
        ro_word.server_status = EXEC_STATUS_CONDITIONS_ERROR;
        ro_bit.exec_conditions_error = 1;
        return;
    }
    else
    {
        ro_bit.exec_conditions_error = 0;
    }

    if(!Do_Action_V_Open_Gate(V1))
        return;
    if(!Do_Action_V_Open_Gate(V2))
        return;
    if(!Do_Action_V_Open_Gate(V3))
        return;
    if(ro_word.server_status == STATUS_IDLE)
    {
        srd_desc[T1].limit = IO_EXPORT_READY;
        srd_desc[T1].srd->limit_step = T1_IMPORT_LIMIT_BUFFER_STEP;
        Do_Action_T_Trans_To_Target(T1, rw_word.mp[T1].max_distance, rw_word.mp[T1].max_speed);
    }

    Update_IO();
    if( Rack_Exist(IMPORTL) || Rack_Exist(EXPORT) || Rack_Exist(IMPORTR))
    {
        ro_word.server_status = EXEC_STATUS_CONDITIONS_ERROR;
        ro_bit.exec_conditions_error = 1;
        return;
    }
    else
    {
        ro_bit.exec_conditions_error = 0;
    }

    Do_Action_Home();
}

void Do_Action_Disable()
{
    uchar i = 0;
    for (i = 0; i < MACHINE_COUNT; ++i)
        IO_Reset(IO_S1_EN + i);
}

bit Do_Action_S_Push_Racks_To_Import(bit home_s, uchar role)
{
    bit result = 1;
    SpeedRampData *srd = srd_desc[role].srd;
    uchar s_index = role - S1;
    uchar another_role = (role == S1 ? S2 : S1);

    Clear_Limit(role);

    srd_desc[role].limit = (role == S1 ? IO_IMPORTL_READY : IO_IMPORTR_READY);
    srd_desc[role].limit2 = (role == S1 ? IO_S1_LIMIT : IO_S2_LIMIT);

    // 如果试管架已在目标节点
    if(Rack_Exist(IMPORTL) || Rack_Exist(IMPORTR) || Rack_Exist(EXPORT))
    {
        return 1;
    }

    if(!Do_Action_V_Close_Gate(s_index ? V1 : V2))
        return 0;
//    if(!Do_Action_V_Open_Gate(s_index ? V2 : V1))
//        return 0;
    if (!hasSampleRack_onCnvBelt())
    {
        if (!IO_Read(IO_S1_HOME + role) && me_state[role] != ME_STATE_WORKING)
            ;//return rw_word.mp[role].max_distance * (-1);

        if (IO_Read(IO_S1_LIMIT + role))
        {
            me_state[role] = ME_STATE_RESET;
            event[role] = EVENT_BUF_EMPTY;
            //motorGotoHome(V3);
            //return rw_word.mp[role].max_distance * (-1);
        }
        //return rw_word.mp[role].max_distance;
    }
    // 如果另一个电机在限位位置，执行一次复位,以防试管架传输时碰到推手
    if(IO_Read(role == S1 ? IO_S2_LIMIT : IO_S1_LIMIT))
    {
        if(!IO_Read(srd_desc[another_role].home)) {
            Do_Action_Reset(another_role,((ushort*)&rw_word.s1_max_speed2)[another_role]);
        }
    }

    // 如果在电机限位位置，执行一次复位动作
    // 同时电机在最大位置pos为max_distance 时,可能为电机丢步并未运行,可执行一次复位动作
    // 只要不是在(不含首次)自动推送模式,不在复位位置应当复位一次
    if(IO_Read(srd_desc[role].limit2) || ro_word.pos[role] >= rw_word.mp[role].max_distance
            || (!IO_Read(srd_desc[role].home) && auto_key_pending[s_index] < 2))
    {
        if(!IO_Read(srd_desc[role].home)) {
            Do_Action_Reset(role,((ushort*)&rw_word.s1_max_speed2)[s_index]);
            if (!Rack_Exist(IMPORTL) && !Rack_Exist(IMPORTR))  {
                return 0;
            }
        }
    }

    Init_Move(role);
    srd->update = Move_To_Update;
    srd->target = rw_word.mp[role].max_distance;

    speed_cntr_Move(srd,
                    srd->target - ro_word.pos[role],
                    rw_word.mp[role].max_speed>>1);

    mkey_changed[role] = 0;
    while(srd->running)
    {
        Process_Main_Loop();
    }

    if(!srd->hit_limit && !Ignore_Import_Ready(s_index))
    {
        if(!srd->hit_limit2)
        {
            Post_Event(role, EVENT_LIMIT_ERROR);
            if(!mkey_changed[role])
            {
                Set_RO_Bit(S1_LIMIT_SENSOR_ERROR + s_index);
                ro_word.server_status = S1_STATUS_LIMIT_SENSOR_ERROR + s_index;
            }
            return 0;
        }
        else
        {
            Reset_RO_Bit(S1_LIMIT_SENSOR_ERROR + s_index);
        }

        if(!Ignore_Import_Ready(s_index))
        {
            /*！ 这里不需要置错误状态，因为这只表示试管架缓存空了 */
            result = 0;
        }
        else
        {
            Reset_RO_Bit(RACK_READY_IMPORTL_ERROR + s_index);
            ro_word.rack_importl_refer_count += 1;
        }
    }
    else
    {
        Reset_RO_Bit(S1_LIMIT_SENSOR_ERROR + s_index);
        Reset_RO_Bit(RACK_READY_IMPORTL_ERROR + s_index);
        ro_word.rack_importl_refer_count += 1;
    }

    if(home_s)
    {
         Do_Action_Reset(role, rw_word.mp[role].max_speed);
    }

    if(ro_word.server_status == STATUS_IDLE && me_state[role - S1] == ME_STATE_IDLE) {
        Do_Action_V_Close_Gate(V1 + s_index);
    }

//    if(srd->hit_limit2)
//    {
//        Post_Event(role, EVENT_BUF_EMPTY);
//        Process_Main_Loop();
//        // 如果为空,关闭闸门
//        //Do_Action_V_Close_Gate(V1 + role);
//    }

    return result;
}

// 辅助传感器检查到试管架存在 返回1
bit Auxiliary_Rack_Exist()
{
    if (fixed_active && !IO_Read(IO_RACK_FIXED))
        return 1;
    if (tube_active && IO_Read(IO_TUBE_EXIST))
        return 1;
    if (hat_active && IO_Read(IO_HAT_EXIST))
        return 1;
    return 0;
}

void Clear_Auxiliary()
{
    fixed_active = 0;
    tube_active = 0;
    hat_active = 0;
}

void Do_Action_T1_Trans_Back_Import(bit outfrom)
{
    uchar role = T1;
    SpeedRampData *srd = srd_desc[role].srd;
    Clear_Limit(role);

    srd_desc[role].limit = IO_IMPORTR_READY;

    if (Rack_Exist(IMPORTL) || Rack_Exist(IMPORTR))
    {
        // 试管架存在
        Set_RO_Bit(EXEC_CONDITIONS_ERROR);
        ro_word.server_status = EXEC_STATUS_CONDITIONS_ERROR;
        return;
    }
    else
        Reset_RO_Bit(EXEC_CONDITIONS_ERROR);

    if (outfrom)
    {
        if (!Do_Action_V_Open_Gate(V3))
            return;
    }

    Init_Move(role);
    ro_word.pos[role] = 0;
    srd->update = Move_To_Update;
    srd->target = -srd->limit_target;
    srd->limit_step = T1_BACK_LIMIT_BUFFER_STEP;

    speed_cntr_Move(srd,
                    srd->target - ro_word.pos[role],
                    rw_word.mp[role].max_speed);

    while (srd->running)
        Process_Main_Loop();

    if (!srd->hit_limit)
    {
        Set_RO_Bit(RACK_READY_EXPORT_ERROR);
        ro_word.server_status = RACK_STATUS_READY_EXPORT_ERROR;
    }
    else
    {
        Reset_RO_Bit(RACK_READY_EXPORT_ERROR);
    }
}

void Do_Action_T1_Trans_Out()
{
    uchar role = T1;
    bit reverse = 0;
    SpeedRampData *srd = srd_desc[role].srd;

    Clear_Limit(role);
    srd_desc[role].limit = IO_EXPORT_READY;

//    if(!Do_Action_V_Open_Gate(V3))
//        return;

    Do_Action_Reset_NoWait(V3);

    rw_bit.export_stop_triggered = 0;
    Init_Move(role);
    ro_word.pos[role] = 0;
    srd->update = T1_Move_To_Update;
    srd->target = reverse ? -rw_word.mp[role].max_distance : rw_word.mp[role].max_distance;
    srd->limit_step = reverse ? (T1_OUT_BUFFER_STEP << 1) : T1_OUT_BUFFER_STEP;

    speed_cntr_Move(srd,
                    srd->target- ro_word.pos[role],
                    rw_word.mp[role].max_speed);

    while(srd->running)
    {
        Process_Main_Loop();
        if(rw_bit.export_stop_triggered)
        {
            rw_bit.export_stop_triggered = 0;
            srd->step_left = T1_EXPORT_LIMIT_BUFFER_STEP;
        }
    }

    if(!srd->hit_limit && !Ignore_Export_Ready())
    {
        Set_RO_Bit(RACK_READY_EXPORT_ERROR);
        ro_word.server_status = RACK_STATUS_READY_EXPORT_ERROR;
    }
    else
    {
        Reset_RO_Bit(RACK_READY_EXPORT_ERROR);
        ro_word.rack_importl_refer_count = 0;
        ro_word.rack_importr_refer_count = 0;
        ro_word.rack_export_refer_count  = 0;
    }

    rack_ready_export = 0;
    // 检测到不遮挡或忽略传感器才关闭闸刀
//    if(!IO_Read(IO_EXPORT_READY) || Ignore_Export_Ready())
//        Do_Action_V_Close_Gate(V3);
    transportIn.sampleRackOnConveyor = 0;
    transportIn.endflag = 0;
}

void Do_Action_S_T1_Trans_In_Out()
{
//    Do_Action_Trans_In();
//    Do_Action_T1_Trans_Out();
      bit role = rw_word.action_arg[0] & 0x01 ? S2 : S1;
      if(Do_Action_S_Push_Racks_To_Import(0, role))
          Do_Action_T1_Trans_Out();
}

void Do_Action_Trans_Next_Station()
{
}

void Do_Action_T_Trans_To_Target(uchar role, long target, ushort speed)
{
    assert(role == T1);
    ro_word.pos[role] = 0;
    Do_Action_Move_To(role, target, speed);
}

////////////////////////////////////////////////////////////////////////////////
/// \brief Process_Action
///
void Process_Action()
{
    long target;
    uchar role = rw_word.action & 0x00FF;
    switch (rw_word.action & 0x00FF)
    {

    case STANDBY:
        Do_Action_StandBy();
        ps_server_busy = 0;
        break;
    case MRESET:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_Home();
        ps_server_busy = 0;
        break;
    case SELFTEST:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_Selftest();
        ps_server_busy = 0;
        break;
    case TRANS_IN:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_Trans_In();
        ps_server_busy = 0;
        break;
    case T1_TRANS_OUT:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_T1_Trans_Out();
        ps_server_busy = 0;
        break;

    case S_T1_TRANS_IN_OUT:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_S_T1_Trans_In_Out();
        ps_server_busy = 0;
        break;
    case TRANS_NEXT_STATION:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_Trans_Next_Station();
        ps_server_busy = 0;
        break;
    case S_PUSH_RACKS_TO_IMPORT:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        role = rw_word.action_arg[0] & 0x01 ? S2 : S1;
        Do_Action_S_Push_Racks_To_Import(0, role);
        ps_server_busy = 0;
        break;
    case T1_TRANS_TO_TARGET:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        target = (long)(rw_word.action_arg[0] << 16 | rw_word.action_arg[1]);
        role = T1 + rw_word.action - T1_TRANS_TO_TARGET;
        srd_desc[role].limit = NULL_IN;
        srd_desc[role].limit2 = NULL_IN;
        srd_desc[role].limit3 = NULL_IN;
        Do_Action_T_Trans_To_Target(role, target, rw_word.action_arg[2]);
        ps_server_busy = 0;
        break;
    case OPEN_BUFL_GATE:
    case OPEN_BUFR_GATE:
    case OPEN_EXPORT_GATE:
    case CLOSE_BUFL_GATE:
    case CLOSE_BUFR_GATE:
    case CLOSE_EXPORT_GATE:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        role -= OPEN_BUFL_GATE;
        if (role&1)
            Do_Action_V_Close_Gate(V1 + (role >> 1));
        else
            Do_Action_V_Open_Gate(V1 + (role >> 1));
        ps_server_busy = 0;
        break;
    case HOME_S1:
    case HOME_S2:
    ps_server_busy = 1;
    ro_word.server_status = STATUS_IDLE;
    if(!IO_Read(IO_S1_HOME + (rw_word.action - HOME_S1)))
    {
        Do_Action_Reset(S1 + (rw_word.action - HOME_S1),((ushort*)&rw_word.s1_max_speed2)[(rw_word.action - HOME_S1)]);
    }
    ps_server_busy = 0;
    break;
    case HOME_V1:
    case HOME_V2:
    case HOME_V3:
    ps_server_busy = 1;
    ro_word.server_status = STATUS_IDLE;
    if(!IO_Read(IO_V1_HOME + (rw_word.action - HOME_V1)))
    {
        Do_Action_Reset(V1 + (rw_word.action - HOME_V1),rw_word.mp[role].max_speed);
    }
    ps_server_busy = 0;
    break;
    case DISABLE_MOTOR: // 解锁所有电机
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_Disable();
        ps_server_busy = 0;
        break;

#ifdef PRODUCT_DEBUG
    case Z_MOVE_TO:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        Do_Action_Z_Move_To(rw_word.z_target, rw_word.z_max_speed);
        ps_server_busy = 0;
        break;
    case DISABLE_MOTOR:
        ps_server_busy = 1;
        ro_word.server_status = STATUS_IDLE;
        IO_Z_ENABLE(0);
        ps_server_busy = 0;
        break;
#endif
    default:
        break;
    }
}

void Main_Loop(void)
{
    uchar role;
    Update_WatchDog();
    LED_BLINK();

    Update_IO();

    for (role = S1; role < MACHINE_COUNT; ++role)
    {
        if (srd_desc[role].srd->need_cleanup && srd_desc[role].srd->cleanup)
            srd_desc[role].srd->cleanup(role);
    }

    // 一帧消息接收完成
    if (uart0_rx_pending && Uart0_FrameEnded())
    {
        uart0_rx_pending = 0;
        REN0 = 0;
        usart_interrupt_disable(USART2, USART_INT_RBNE);
        Process_Request();
    }
    // 应答结束, 允许接收
    if (!REN0 && !uart0_tx_pending)
    {
        uart0_len = 0;
        uart0_rx_pending = 0;
        REN0 = 1;
        usart_interrupt_enable(USART2, USART_INT_RBNE);
    }

    Process_Scanbar();
    Beep_Cntrol();
}

void Process_Main_Loop(void)
{
    Main_Loop();

    Process_Start_Event(KEY_STARTL);
    Process_Start_Event(KEY_STARTR);
    Process_Rack(KEY_STARTL);
    Process_Rack(KEY_STARTR);
    Key_Led_Ctrl(KEY_STARTL);
    Key_Led_Ctrl(KEY_STARTR);

    if (pending_action)
        longjmp(main_loop_env, 1);
}

/**
 * @brief Update the state of the block motor
 *
 * This function updates the state of the block motor
 * based on the current state and site.
 *
 * @param TrackExitMotor Pointer to the block motor structure
 * @return None
 *
 * @note The function assumes that the block motor structure is properly initialized.
 *
 * @example
 * Update_TrackExitMotor(&TrackExitMotor);
 */

struct TransportIn transportIn = {
    TRACK_EXIT_MOTOR_SITE_ORIGIN, // site
    TRACK_EXIT_MOTOR_SITE_START,  // previousSite
    0,            // testTubeSite
    TIMER_STOPED, // time
    0,            // end flag
    0,            // sampleRackOnConveyor
    0,            // nextTubeExist
    0};

int transportIn_loopCondition(void)
{
    int result;
    int i;
    for (i = 0; i < MACHINE_COUNT; i++)
    {
        if (i == T1)
            continue;
        result = srd_desc[i].srd->running;
        if (result == 1)
            return 0;
    }
    return 1;
}

void transportIn_prepared_action(void)
{
    int result;
    result = sampleRackOnConveyor;
    if (result == 1)
        return;
    result = srd_desc[T1].srd->running;
    if (result == 1)
        Stop_Motor(T1);
    return;
}

int check_sampleRack_exists(void)
{
    int result;
    result = IO_Read(IO_BASKETL_EXIST);
    if (result == 1)
        return 0;
    result = IO_Read(IO_BASKETR_EXIST);
    if (result == 1)
        return 0;
    return 1;
}

int sampleRack_isReachTargetSite()
{
    if (IO_Read(IO_IMPORTR_READY) || IO_Read(IO_IMPORTL_READY))
    {
        return 0;
    }
    if (transportIn.site_previous != transportIn.site)
    {
        return 0;
    }
    return IO_Read(IO_RACK_FIXED);
}

int motor_isRuning(uint32_t role)
{
    return srd[role].running;
}

int transIn_loopCondition(void)
{
    int role[] = {S1, S2, R1, R2, V3};
    int i;

    if (motor_isRuning(R1) && transportIn.ScannedBarcode)
        return 1;

    for (i = 0; i < 5; i++)
    {
        if (motor_isRuning(role[i]))
            return 0;
    }
    return 1;
}

int transIn_endCondition(void)
{

    if (!transIn_loopCondition()) {
        return 0;
    }
    if (transportIn.endflag)
    {
        if (IO_Read(IO_RACK_ARRIVE)) {
            return 1;
        }
        transportIn.endflag = 0;
    }

    if (transportIn.site_previous < TRACK_EXIT_MOTOR_SITE_ORIGIN)
    {
        return 0;
    }
    if (transportIn.site != transportIn.site_previous)
    {
        return 0;
    }
    transportIn.endflag = 1;
    return 0;
}

int hasSampleRack_onCnvBelt(void)
{
    int role[] = {
        IO_IMPORTL_READY,
        IO_IMPORTR_READY,
        // IO_EXPORT_READY,
    };
    int i = sizeof (role) / sizeof(role[0]);
    int j = 0;
    if (!IO_Read(IO_EXPORT_READY) && IO_Read(IO_V3_HOME))
        transportIn.sampleRackOnConveyor = 0;

    if (transportIn.sampleRackOnConveyor)
        return 1;

    transportIn.sampleRackOnConveyor = 0;
    for (; i > j; j++)
    {
        transportIn.sampleRackOnConveyor |= IO_Read(role[j]);
    }
    return transportIn.sampleRackOnConveyor;
}

void T1_Do_Action_Move_To_Frist_Target(void)
{
    uchar role = T1;
    SpeedRampData *srd = srd_desc[role].srd;

    ro_word.pos[role] = 0;
    Init_Move(role);
    srd->update = Move_To_Update;
    srd->target = rw_word.mp[T1].max_distance;

    speed_cntr_Move(srd,
                    srd->target - ro_word.pos[role],
                    rw_word.mp[role].max_speed);

    while (srd->running) {
        Process_Main_Loop();
        if (!IO_Read(IO_RACK_FIXED)) {
            srd->step_left = 50;
            break;
        }
    }
}

uchar Do_Action_R1_Scan(void)
{
    uchar role = R1;
    SpeedRampData *srd = srd_desc[role].srd;

    Init_Move(role);
    srd->update = Move_To_Update;
    srd->target = 8800*1;

    ro_word.rn_pos[role-R1] = 0;
    speed_cntr_Move(srd,
                    srd->target - ro_word.rn_pos[role-R1],
                    rw_word.mp[role].max_speed);

    while (srd->running) {

        Process_Main_Loop();
        if (transportIn.ScannedBarcode) {
            srd->step_left = 100;
            return 1;
        }
    }
    return 0;
}

void start_tubeRotateMotor()
{
    if (!IO_Read(IO_R2_HOME))
        Do_Action_R1_Scan();

}

bit Do_Action_R2_Move_LimitDown(uchar isTallTube)
{
    if (isTallTube)
    {
        // 防止上次是75管的参数当前是100管容易压坏
        if (rw_word.r2_desc_step > 1000)
            Do_Action_Move_To(R2,800,rw_word.mp[R2].max_speed);
        else
            Do_Action_Move_To(R2,rw_word.r2_desc_step,rw_word.mp[R2].max_speed);
    }
    else
    {
        Do_Action_Move_To(R2,rw_word.r2_desc_step,rw_word.mp[R2].max_speed);
    }
    return 1;
}

static void Scanned_barcode_handle()
{
    // 复位扫码升级电机
    if (!IO_Read(IO_R2_HOME))
        Do_Action_Reset(R2,rw_word.mp[R2].max_speed);
    if (transportIn.site_previous < TRACK_EXIT_MOTOR_SITE_ORIGIN)
        transportIn.site_previous++;
    transportIn.ScannedBarcode = 0;
    if (transportIn.site < TRACK_EXIT_MOTOR_SITE_FIRST || transportIn.site > TRACK_EXIT_MOTOR_SITE_FIFTH)
        return;
    SET_SPECIFIC_BIT(ro_word.rack_flag, transportIn.site - TRACK_EXIT_MOTOR_SITE_FIRST, transportIn.nextTubeExist);
}
// 更新电机驱动、添加错误反馈
long setTrackExitMotorSite(void)
{
    uint32_t role = V3;
    long target;
    SpeedRampData *data = srd_desc[role].srd;
    int dir;

    if (data->running)
        return 0;
    if (IO_Read(IO_V3_HOME) && IO_Read(IO_EXPORT_READY))
        return 0;
    if (IO_Read(IO_V3_LIMIT))
    {
        transportIn.site = TRACK_EXIT_MOTOR_SITE_START;
        if (transportIn.site_previous == TRACK_EXIT_MOTOR_SITE_START)
            return 0;
    }
    else if (IO_Read(IO_V3_HOME))
    {
        transportIn.site = TRACK_EXIT_MOTOR_SITE_ORIGIN;
        if (transportIn.site_previous == TRACK_EXIT_MOTOR_SITE_ORIGIN)
            return 0;
    }
    if (transportIn.site_previous == transportIn.site)
        return 0;
    dir = (transportIn.site > transportIn.site_previous) ? -1 : 1;
    if (transportIn.site > TRACK_EXIT_MOTOR_SITE_START && transportIn.site < TRACK_EXIT_MOTOR_SITE_ORIGIN)
        TrackExitMotor_coordinate[transportIn.site] = rw_word.scan_pos[transportIn.site - TRACK_EXIT_MOTOR_SITE_FIRST];

    target = abs((int)(TrackExitMotor_coordinate[transportIn.site] - TrackExitMotor_coordinate[transportIn.site_previous]));
    data->dir = (dir == 1) ? 1 : 0;
    return target * dir;
}

long motor_target(uint32_t role)
{
    int dir;

    if (role == V1)
    {
        dir = IO_Read(IO_V1_HOME) ? 1 : -1;
        return rw_word.mp[role].max_distance * dir;
    }
    if (role == V2)
    {
        dir = IO_Read(IO_V2_HOME) ? 1 : -1;
        return rw_word.mp[role].max_distance * dir;
    }
    if (role == V3)
    {
        return setTrackExitMotorSite();
    }
    if (role == T1 && (rw_word.action & 0x00FF) == MRESET)
    {
        dir = IO_Read(IO_EXPORT_READY) ? -1 : 1;
        return rw_word.mp[role].max_distance * dir;
    }
    if (role == R2)
    {
        dir = IO_Read(IO_R2_HOME) ? -1 : 1;
        return rw_word.r2_desc_step * dir;
    }
    return rw_word.mp[role].max_distance;
}

int motor_run(uint32_t role)
{
    SpeedRampData *data = &srd[role];    // 获取指定电机角色的速度爬升数据
    long i;                              // 目标位置和当前位置的差值
    uint16_t speed;                      // 电机运行速度
    Init_Move(role);                     // 初始化电机运动相关参数
    data->update = Move_To_Update;
    i = motor_target(role);              // 计算目标位置与当前位置的差值
    data->target = srd[role].reset_step; // 保存复位步数 (可能用于某些特殊情况)
    data->role = role;
    speed = rw_word.mp[role].max_speed;  // 获取指定电机角色的最大速度

    // 如果是S1或S2电机，并且目标位置大于0，则使用较低的速度
    if (role <= S2 && i > 0)
    {
        speed = 1000; // 使用较低的速度 (314 * 8)
    }
    if (role == T1 && transportIn.site_previous > TRACK_EXIT_MOTOR_SITE_FIFTH)
    {
        speed = 314 * 2; // 使用较低的速度 (314 * 8)
    }

     // Start the speed control and execute the motor movement.
    speed_cntr_Move(data,
                    i,      // 目标位置与当前位置的差值
                    speed); // 电机运行速度

    // 如果目标位置与当前位置相同 (i == 0)，则返回 0 (未启动)，否则返回 1 (已启动)
    return i == 0 ? 0 : 1;
}

int conveyorBelt_motor_start(void)
{
    if (!motor_isRuning(T1))
        return motor_run(T1);
    return 0;
}

void update_rack_flag(void)
{
    uchar rack_flag;
    int i;

    rack_flag = 0;
    for (i = 0; i < 5; i++)
    {
        rack_flag<<=1;
        if (!all_zeros(ro_word.barcodes[i], 16))
            rack_flag |= 1;
    }
    ro_word.rack_flag &= 0xFFE0;
    ro_word.rack_flag |= rack_flag;
}

int Do_Action_Trans_In()
{
    uint32_t role = rw_word.action_arg[0] & 0x01 ? S2 : S1;
    uint32_t check = 0;
    uint32_t *stamp = NULL;
    int result = 1;
    bit active_scan_only = 0;
    ulong timeout = 0;

    if (IO_Read(IO_EXPORT_READY) && IO_Read(IO_V3_HOME))
        return 1;

    // 按钮请求动作下，检测到上一次为到位错误事件，且扫描到了部分的条码
    if(me_state[role] == ME_STATE_WORKING && me_lastEvent[role] == EVENT_EXPORT_READY_ERROR
            && Mbar_Count() && !Rack_Scan_Finished())
        active_scan_only = 1;

    rack_ready_export = 0;
    if(!rw_word.app_arg1.disable_scanner)
    {
        if(!active_scan_only)
            Start_Scan(0);
        else
            Active_Scan();
    }

    if(!active_scan_only)
        Reset_Fix();
    result = Do_Action_S_Push_Racks_To_Import(0, role);
    // 用户通过按钮取消了传输
    if((me_state[role] != ME_STATE_WORKING) && (pending_role == (!role ? ACTION_PENDING_KEY1_EVENT : ACTION_PENDING_KEY2_EVENT)))
        return 0;
    if(result && ro_word.server_status == STATUS_IDLE)
    {
        // Initialize the track exit motor site to the origin and the previous site to the start
        // 将轨道出口电机位置初始化为原点，将上一个位置初始化为起点
        transportIn.site = TRACK_EXIT_MOTOR_SITE_ORIGIN;// 6
        transportIn.site_previous = TRACK_EXIT_MOTOR_SITE_START;// 0
        // Set the timestamp to -1
        stamp = &transportIn.stamp;
       *stamp = 0xFFFFFFFF;
        // Start the scanning process
        Start_Scan(0);
        // Start the V3 motor
        Do_Action_DegradedMotor_Move_To();
        // Set the previous site of the track exit motor to the first position
        // 将轨道出口电机的前一个位置设置为第一个位置
        transportIn.site_previous = TRACK_EXIT_MOTOR_SITE_FIRST;
        transportIn.ScannedBarcode = 0;
        transportIn.endflag = 1;
        if (transportIn.sampleRackOnConveyor == 1 && !IO_Read(IO_EXPORT_READY))
            transportIn.sampleRackOnConveyor = 0;
        // Continue the loop until the transportation in process is completed
        // 判断是否扫描到最后一个试管架
        while (!transIn_endCondition())
        {
            // Execute the main loop
            Beep_Cntrol();
            Process_Main_Loop();
            // 监听是否获取到样本码
            if (!transIn_loopCondition())
                continue;
            // 如果样品架未到达目标位置，启动传送带电机和V3电机
            if (!sampleRack_isReachTargetSite())
            {
                timeout = 0;
                // 复位扫码升级电机
                if (!IO_Read(IO_R2_HOME))
                    Do_Action_Reset(R2,rw_word.mp[R2].max_speed);
                if (!test_delay_nonBlock(stamp, 10))
                    continue;
                if (transportIn.site_previous != transportIn.site)
                {
                    transportIn.nextTubeExist = IO_Read(IO_TUBE_EXIST);
                    transportIn.isTallTube = IO_Read(IO_HAT_EXIST);
                }
                if (motor_run(V3))
                {
                    if (transportIn.site_previous == TRACK_EXIT_MOTOR_SITE_FIRST)
                    {
                        T1_Do_Action_Move_To_Frist_Target();
                        transportIn.nextTubeExist = IO_Read(IO_TUBE_EXIST);
                        transportIn.isTallTube = IO_Read(IO_HAT_EXIST);
                        srd_desc[T1].limit2 = IO_RACK_FIXED;
                        Do_Action_T_Trans_To_Target(T1,rw_word.mp[T1].max_distance,rw_word.mp[T1].max_speed>>1);
                    }
                    else
                    {
                        if (transportIn.site_previous <= TRACK_EXIT_MOTOR_SITE_FIFTH)
                        {
                            Do_Action_T_Trans_To_Target(T1,600,rw_word.mp[T1].max_speed>>1);
                            srd_desc[T1].limit2 = IO_RACK_FIXED;
                            Do_Action_T_Trans_To_Target(T1,rw_word.mp[T1].max_distance,rw_word.mp[T1].max_speed>>1);
                            srd_desc[T1].limit2 = NULL_IN;
                            Do_Action_T_Trans_To_Target(T1,800,rw_word.mp[T1].max_speed>>1);
                        }
                        else
                        {
                            Do_Action_T_Trans_To_Target(T1,600,rw_word.mp[T1].max_speed>>1);
                        }
                    }
                    if (transportIn.site_previous == TRACK_EXIT_MOTOR_SITE_FIFTH)
                    {
                        Do_Action_T_Trans_To_Target(T1,600,rw_word.mp[T1].max_speed>>1);
                    }
                }
                continue;
            }
            //  If there is no next test tube, handle the scanned barcode
            //  如果试管不存在继续进行处理下一个
            if (!transportIn.nextTubeExist)
            {
                check = 0;
                Scanned_barcode_handle();
                continue;
            }
            // If a barcode is scanned, handle the scanned barcode and reset the check variable
            // 如果扫描了条形码，请处理扫描的条形码并重置校验变量
            if (transportIn.ScannedBarcode)
            {
                check = 0;
                Scanned_barcode_handle();
            }
            else
            {
                if (transportIn.site >= 1 && transportIn.site <= 5)
                {
                    timeout++;
                    if (timeout >= 10000) 
                    {
                        // If no barcode is scanned, lower the lift motor and start the tube rotation motor
                        // 如果没有扫描到条形码，降低升降电机并启动试管旋转电机
                        Do_Action_R2_Move_LimitDown(transportIn.isTallTube);
                        start_tubeRotateMotor();
                        // If the check variable exceeds 1, handle the scanned barcode and reset the check variable
                        // 如果校验变量超过1，则处理扫描的条形码并重置校验变量
                        if (check++ > 1)
                        {
                            check = 0;
                            Scanned_barcode_handle();
                            continue;
                        }
                    }
                }
            }
        }

        Do_Action_Reset(V3,rw_word.mp[V3].max_speed);
        Stop_Scan(0);

        Reset_RO_Bit(RACK_READY_EXPORT_ERROR);
        ++ro_word.rack_number;
        ro_word.rack_importl_refer_count = 0;
        ro_word.rack_importr_refer_count = 0;
        ro_word.rack_export_refer_count += 1;
        rack_ready_export = 1;

        // 更新试管扫码标志
        update_rack_flag();
    }

    if(!result && ro_word.server_status == (S1_STATUS_LIMIT_SENSOR_ERROR + role))
    {
        Set_RO_Bit(RACK_READY_EXPORT_ERROR);
        // S限位错误，有可能试管架在export，相互挤压导致s推送不到位，尝试一次传输试管架
        //Do_Action_T1_Trans_To_Export_Ready(role);
        // 没有检测到试管架，重置之前的错误
        if(ro_word.rack_export_refer_count == 0)
        {
            Post_Event(role, EVENT_LIMIT_ERROR);
            ro_word.server_status = (S1_STATUS_LIMIT_SENSOR_ERROR + role);
        }
        else
            ro_word.server_status = STATUS_IDLE;
    }
    return result;
}
